<script setup lang="ts">
import { computed, onMounted, watch } from 'vue'
import { useMonacoEditor } from './index'

type MonacoLanguage = 'editorWorkerService' | 'typescript' | 'json' | 'html'
type Dimension = string | number

interface EditorOptions {
  [key: string]: unknown
  // You can add specific Monaco editor options here if needed
  // Example:
  // theme?: string
  // fontSize?: number
  // minimap?: { enabled: boolean }
}

const props = withDefaults(
  defineProps<{
    width?: Dimension
    height?: Dimension
    language?: MonacoLanguage
    editorOption?: EditorOptions
    modelValue: string | undefined
  }>(),
  {
    width: '100%',
    height: '100%',
    language: 'json',
    editorOption: () => ({}),
    modelValue: '',
  },
)

const emit = defineEmits<{
  (e: 'blur'): void
  (e: 'update:modelValue', value: string): void
}>()

const monacoEditorStyle = computed(() => ({
  width: typeof props.width === 'string' ? props.width : `${props.width}px`,
  height: typeof props.height === 'string' ? props.height : `${props.height}px`,
}))

const { monacoEditorRef, createEditor, updateVal, updateOptions, getEditor } = useMonacoEditor(
  props.language,
)

onMounted(() => {
  const monacoEditor = createEditor(props.editorOption)

  if (!monacoEditor) return

  updateMonacoVal(props.modelValue || '')

  monacoEditor.onDidChangeModelContent(() => {
    const currentValue = monacoEditor.getValue()
    emit('update:modelValue', currentValue)
  })

  monacoEditor.onDidBlurEditorText(() => {
    emit('blur')
  })
})

watch(
  () => props.modelValue,
  (newValue) => {
    updateMonacoVal(newValue ?? '')
  },
)

function updateMonacoVal(value: string | undefined): void {
  const editor = getEditor()
  if (!editor || value === undefined) return

  const currentValue = editor.getValue()
  if (value !== currentValue) {
    updateVal(value)
  }
}

defineExpose({
  updateOptions: (options: EditorOptions) => updateOptions(options),
})
</script>

<template>
  <div ref="monacoEditorRef" :style="monacoEditorStyle"></div>
</template>
